from flask import Blueprint, render_template, request, jsonify, session, redirect, url_for, flash
from config import app_state, MYSQL_CONFIG
from services import generate_schedule, generate_bed_layout, generate_seat_layout, get_schedule_analysis
from db import (get_schedule_by_date, save_schedule_to_db, save_bed_layout_to_db, save_seat_layout_to_db,
               verify_user, create_user, check_username_exists, get_all_room_numbers,
               save_bed_change_record, save_seat_change_record, save_schedule_change_record, get_records, get_record_count,
               update_user_room_permissions, get_all_users, delete_user, get_all_roles, update_user_information)
from functools import wraps
import relief
import json
from datetime import datetime, timedelta, date
from collections import defaultdict
import traceback
import mysql.connector

bp = Blueprint('main', __name__)

# 登录验证装饰器
def login_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if 'user_id' not in session:
            return redirect(url_for('main.login'))
        return f(*args, **kwargs)
    return decorated_function

@bp.route('/login', methods=['GET', 'POST'])
def login():
    error = None
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        
        if not username or not password:
            error = '请输入用户名和密码'
        else:
            user = verify_user(username, password)
            if user:
                session['user_id'] = user['id']
                session['username'] = user['username']
                session['user_type'] = user['user_type']
                session['role_id'] = user['role_id'] if user['role_id'] else 0
                session['room_numbers'] = user['room_numbers'].split(',') if user['room_numbers'] else []
                return redirect(url_for('main.index'))
            else:
                error = '用户名或密码错误'
    
    return render_template('login.html', error=error)

@bp.route('/register', methods=['GET', 'POST'])
def register():
    error = None
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        confirm_password = request.form.get('confirm_password')
        full_name = request.form.get('full_name')
        phone = request.form.get('phone')
        role_id = request.form.get('role_id')
        
        # 普通用户注册，无房间权限
        user_type = 'normal'
        room_numbers = []
        
        if not username or not password or not confirm_password:
            error = '请填写所有必填字段'
        elif password != confirm_password:
            error = '两次输入的密码不一致'
        elif check_username_exists(username):
            error = '用户名已存在'
        else:
            if create_user(username, password, room_numbers, user_type, full_name, phone, role_id):
                return redirect(url_for('main.login'))
            else:
                error = '注册失败，请稍后再试'
    
    # 获取角色列表用于前端显示
    roles = get_all_roles()
    return render_template('register.html', error=error, roles=roles)

@bp.route('/logout')
def logout():
    session.clear()
    return redirect(url_for('main.login'))

@bp.route('/')
@login_required
def index():
    """首页路由 - 显示系统概览"""
    with app_state.lock:
        current_data = app_state.persons

    # 确保数据是列表类型
    if not isinstance(current_data, list):
        print(f"无效的数据格式: {type(current_data)}")
        current_data = []

    room_stats = defaultdict(int)
    floor_counts = defaultdict(int)

    for p in current_data:
        room = p.get('room_number', '')
        if room:
            room_stats[room] += 1
            floor_num = room[0] if room else '0'
            floor_counts[floor_num] += 1

    # 获取当前用户信息
    user_type = session.get('user_type', 'normal')
    user_room_numbers = session.get('room_numbers', [])
    
    # 根据用户类型过滤房间信息
    filtered_room_stats = {}
    if user_type != 'normal':  # 管理员可以看到所有房间
        filtered_room_stats = room_stats
    else:  # 普通用户只能看到自己拥有的房间
        for room in user_room_numbers:
            if room in room_stats:
                filtered_room_stats[room] = room_stats[room]
    
    # 重新计算楼层统计信息
    filtered_floor_counts = defaultdict(int)
    for room, count in filtered_room_stats.items():
        floor_num = room[0] if room else '0'
        filtered_floor_counts[floor_num] += count

    # 获取当前用户信息
    current_user = {
        'is_authenticated': 'user_id' in session,
        'username': session.get('username', ''),
        'user_type': user_type
    }
    
    return render_template(
        'index.html',
        floors=dict(sorted(filtered_floor_counts.items())),
        floor_counts=filtered_floor_counts,
        total_persons=sum(filtered_room_stats.values()),
        total_rooms=len(filtered_room_stats),
        current_user=current_user
    )

@bp.route('/rooms')
@login_required
def rooms():
    """房间管理路由 - 显示楼层和房间统计数据"""
    with app_state.lock:
        current_data = app_state.persons

    # 确保数据是列表类型
    if not isinstance(current_data, list):
        print(f"无效的数据格式: {type(current_data)}")
        current_data = []

    room_stats = defaultdict(int)
    floor_counts = defaultdict(int)

    for p in current_data:
        room = p.get('room_number', '')
        if room:
            room_stats[room] += 1
            floor_num = room[0] if room else '0'
            floor_counts[floor_num] += 1

    # 获取当前用户信息
    user_type = session.get('user_type', 'normal')
    user_room_numbers = session.get('room_numbers', [])
    
    # 根据用户类型过滤房间信息
    filtered_room_stats = {}
    if user_type != 'normal':  # 管理员可以看到所有房间
        filtered_room_stats = room_stats
    else:  # 普通用户只能看到自己拥有的房间
        for room in user_room_numbers:
            if room in room_stats:
                filtered_room_stats[room] = room_stats[room]
    
    # 重新计算楼层统计信息
    filtered_floor_counts = defaultdict(int)
    for room, count in filtered_room_stats.items():
        floor_num = room[0] if room else '0'
        filtered_floor_counts[floor_num] += count

    # 组织楼层数据
    floors = defaultdict(list)
    for room, count in filtered_room_stats.items():
        floor_num = room[0] if room else '0'
        floors[floor_num].append({'number': room, 'count': count})

    # 排序处理
    floors = dict(sorted(floors.items()))
    for floor in floors.values():
        floor.sort(key=lambda x: x['number'])

    # 获取当前用户信息
    current_user = {
        'is_authenticated': 'user_id' in session,
        'username': session.get('username', ''),
        'user_type': user_type
    }
    
    return render_template(
        'rooms.html',
        floors=floors,
        floor_counts=filtered_floor_counts,
        total_persons=sum(filtered_room_stats.values()),
        total_rooms=len(filtered_room_stats),
        current_user=current_user
    )

@bp.route('/profiles')
@login_required
def profiles():
    """人物画像路由 - 显示人物画像页面"""
    # 获取当前用户信息
    current_user = {
        'is_authenticated': 'user_id' in session,
        'username': session.get('username', ''),
        'user_type': session.get('user_type', 'normal')
    }
    
    return render_template(
        'profiles.html',
        current_user=current_user
    )

@bp.route('/medical')
@login_required
def medical():
    """医疗辅助路由 - 显示医疗辅助页面"""
    # 获取当前用户信息
    current_user = {
        'is_authenticated': 'user_id' in session,
        'username': session.get('username', ''),
        'user_type': session.get('user_type', 'normal')
    }
    
    return render_template(
        'medical.html',
        current_user=current_user
    )

@bp.route('/room/<room_number>')
@login_required
def room_detail(room_number):
    """房间详情页 - 增加排班功能和日期选择"""
    # 获取当前用户信息
    user_type = session.get('user_type', 'normal')
    user_room_numbers = session.get('room_numbers', [])
    
    # 检查普通用户是否有权限访问该房间
    if user_type == 'normal' and room_number not in user_room_numbers:
        # 使用flash消息通知用户（需要在模板中添加flash消息显示）
        from flask import flash
        flash('您没有权限访问该房间', 'error')
        return redirect(url_for('bp.index'))
    
    with app_state.lock:
        current_data = app_state.persons
    if not isinstance(current_data, list):
        current_data = []

    filtered = []
    for p in current_data:
        try:
            if (isinstance(p, dict) and
                    str(p.get('room_number')) == room_number and
                    p.get('join_date')):
                # 统一join_date的格式处理
                join_date = p.get('join_date')
                if isinstance(join_date, (datetime, date)):
                    join_date = join_date.strftime('%Y-%m-%d')

                filtered.append({
                    'id': str(p['id'])[:8],
                    'name': p.get('name', '')[:15],
                    'join_date': join_date,
                    'room_number': p.get('room_number'),
                    'FXDJ': p.get('FXDJ', 0),
                    'BHLX': p.get('BHLX', 0)
                })
        except Exception as e:
            print(f"数据过滤错误: {str(e)}")

    sorted_data = sorted(filtered, key=lambda x: x['join_date'])

    # 获取当前周和默认显示周
    current_week = datetime.now().date()
    selected_week = request.args.get('week', current_week.strftime('%Y-%m-%d'))

    # 尝试获取当周值班表、床位数据、座位数据
    schedule_result = get_schedule_by_date(room_number, selected_week)

    # 确保正确处理可能的None值
    if schedule_result:
        schedule = schedule_result.get('schedule_data')
        beddata = schedule_result.get('bed_data')
        seatdata = schedule_result.get('seat_data')
    else:
        schedule = None
        beddata = None
        seatdata = None

    beddata_exists = beddata is not None
    seatdata_exists = seatdata is not None
    schedule_exists = schedule is not None

    # 如果没有值班表，生成一个空结构用于前端显示
    if not schedule_exists:
        # 创建空值班表结构
        schedule = []
        target_date = datetime.strptime(selected_week, '%Y-%m-%d').date()
        days_to_monday = target_date.weekday()
        monday = target_date - timedelta(days=days_to_monday)

        for i in range(7):
            current_date = monday + timedelta(days=i)
            schedule.append({
                'date': current_date.strftime('%Y-%m-%d'),
                'shifts': {
                    '午班': [],
                    '夜班1': [],
                    '夜班2': [],
                    '夜班3': []
                }
            })
    else:
        # 如果从数据库获取到数据，解析JSON
        schedule = json.loads(schedule)

    # 如果没有床位数据，生成一个空结构用于前端显示
    if not beddata_exists:
        beddata = []
    else:
        # 如果从数据库获取到数据，解析JSON
        beddata = json.loads(beddata)

    # 如果没有座位数据，生成一个空结构用于前端显示
    if not seatdata_exists:
        seatdata = []
    else:
        # 如果从数据库获取到数据，解析JSON
        seatdata = json.loads(seatdata)

    # 计算当前周的周一日期
    days_to_current_monday = current_week.weekday()
    current_week_monday = (current_week - timedelta(days=days_to_current_monday)).strftime('%Y-%m-%d')
    
    # 判断选择的日期是否在今天之前
    selected_date = datetime.strptime(selected_week, '%Y-%m-%d').date()
    is_past_date = selected_date < datetime.now().date()

    # 生成未来4周的日期选项
    week_options = []
    for i in range(-2, 3):  # 包括前2周和后2周
        week_date = current_week + timedelta(weeks=i)
        days_to_monday = week_date.weekday()
        monday = week_date - timedelta(days=days_to_monday)
        sunday = monday + timedelta(days=6)
        label = f"{monday.strftime('%m-%d')}至{sunday.strftime('%m-%d')}"
        week_options.append({
            'value': week_date.strftime('%Y-%m-%d'),
            'label': label,
            'is_current': i == 0
        })

    # 获取当前用户信息
    # 创建current_user字典，确保包含所有必要字段
    current_user = {
        'id': session.get('user_id'),
        'username': session.get('username', ''),
        'user_type': user_type,
        'is_authenticated': 'user_id' in session
    }
    
    # 创建room对象，确保包含id和room_number
    room = {
        'id': room_number,
        'room_number': room_number
    }
    
    return render_template(
        'room.html',
        room=room,  # 传递完整的room对象
        room_number=room_number,
        data=sorted_data,
        schedule=schedule,
        schedule_exists=schedule_exists,
        beddata=beddata,
        beddata_exists=beddata_exists,
        seatdata=seatdata,
        seatdata_exists=seatdata_exists,
        total=len(sorted_data),
        week_options=week_options,
        selected_week=selected_week,
        current_week_monday=current_week_monday,
        is_past_date=is_past_date,
        backendBedData=json.dumps(beddata),
        backendSeatData=json.dumps(seatdata),
        current_user=current_user  # 传递统一的current_user字典
    )

@bp.route('/generate_schedule/<room_number>', methods=['POST'])
@login_required
def generate_schedule_endpoint(room_number):
    """生成值班表API - 支持指定日期"""
    try:
        target_date = request.json.get('target_date')
        base_date = datetime.strptime(target_date, '%Y-%m-%d').date() if target_date else None

        with app_state.lock:
            current_data = app_state.persons

        # 过滤指定房间的数据
        filtered = []
        for p in current_data:
            try:
                if (isinstance(p, dict) and
                        str(p.get('room_number')) == room_number and
                        p.get('join_date') and
                        str(p.get('FXDJ', '0')) == '0' and
                        str(p.get('BHLX', '0')) == '0'):
                    filtered.append(p)
            except Exception:
                continue

        # 按加入日期排序
        sorted_data = sorted(filtered, key=lambda x: x['join_date'])

        # 生成排班表
        schedule = generate_schedule(sorted_data, base_date)

        # 获取排班分析报告
        analysis_report = get_schedule_analysis(schedule, sorted_data)

        # 保存到数据库
        if target_date:
            save_success = save_schedule_to_db(room_number, schedule, target_date)
        else:
            save_success = save_schedule_to_db(room_number, schedule)

        return jsonify({
            'success': True,
            'schedule': schedule,
            'analysis_report': analysis_report,  # 返回分析报告
            'saved': save_success
        })
    except Exception as e:
        print(f"生成值班表错误: {str(e)}")
        print(traceback.format_exc())
        return jsonify({
            'success': False,
            'message': f"生成值班表失败: {str(e)}"
        }), 500


@bp.route('/get_schedule_analysis/<room_number>', methods=['GET'])
@login_required
def get_schedule_analysis_endpoint(room_number):
    """获取排班公平性分析数据API"""
    try:
        # 获取当前周的日期
        target_date = request.args.get('target_date', datetime.now().strftime('%Y-%m-%d'))
        base_date = datetime.strptime(target_date, '%Y-%m-%d').date()

        with app_state.lock:
            current_data = app_state.persons

        # 获取房间总人数
        total_persons = []
        for p in current_data:
            try:
                if (isinstance(p, dict) and
                        str(p.get('room_number')) == room_number and
                        p.get('join_date')):
                    total_persons.append(p)
            except Exception:
                continue

        # 过滤指定房间的数据（参与值班的人员）
        filtered = []
        for p in current_data:
            try:
                if (isinstance(p, dict) and
                        str(p.get('room_number')) == room_number and
                        p.get('join_date') and
                        str(p.get('FXDJ', '0')) == '0' and
                        str(p.get('BHLX', '0')) == '0'):
                    filtered.append(p)
            except Exception:
                continue

        # 按加入日期排序
        sorted_data = sorted(filtered, key=lambda x: x['join_date'])

        # 获取排班表
        schedule_result = get_schedule_by_date(room_number, target_date)  # 传递字符串格式的日期
        
        # 解析排班表数据
        if schedule_result and 'schedule_data' in schedule_result:
            try:
                schedule = json.loads(schedule_result['schedule_data'])
            except json.JSONDecodeError:
                schedule = None
        else:
            schedule = None

        # 获取排班分析报告
        analysis_report = get_schedule_analysis(schedule, sorted_data, len(total_persons))

        return jsonify({
            'success': True,
            'analysis_report': analysis_report
        })
    except Exception as e:
        print(f"获取排班分析错误: {str(e)}")
        print(traceback.format_exc())
        return jsonify({
            'success': False,
            'message': f"获取排班分析失败: {str(e)}"
        }), 500

@bp.route('/generate_bed_layout/<room_number>', methods=['POST'])
@login_required
def generate_bed_layout_endpoint(room_number):
    """生成铺位布局API"""
    try:
        target_date = request.json.get('target_date')

        with app_state.lock:
            current_data = app_state.persons

        # 过滤指定房间的数据
        filtered = []
        for p in current_data:
            try:
                if (isinstance(p, dict) and
                        str(p.get('room_number')) == room_number and
                        p.get('join_date')):
                    filtered.append(p)
            except Exception:
                continue

        # 生成铺位布局
        bed_layout = generate_bed_layout(filtered)

        # 保存到数据库
        save_success = save_bed_layout_to_db(room_number, bed_layout, target_date)

        return jsonify({
            'success': True,
            'bed_layout': bed_layout,
            'saved': save_success
        })
    except Exception as e:
        print(f"生成铺位布局错误: {str(e)}")
        print(traceback.format_exc())
        return jsonify({
            'success': False,
            'message': f"生成铺位布局失败: {str(e)}"
        }), 500

@bp.route('/generate_seat_layout/<room_number>', methods=['POST'])
@login_required
def generate_seat_layout_endpoint(room_number):
    """生成座位布局API"""
    try:
        target_date = request.json.get('target_date')

        with app_state.lock:
            current_data = app_state.persons

        # 过滤指定房间的数据
        filtered = []
        for p in current_data:
            try:
                if (isinstance(p, dict) and
                        str(p.get('room_number')) == room_number and
                        p.get('join_date')):
                    filtered.append(p)
            except Exception:
                continue

        # 生成座位布局
        seat_layout = generate_seat_layout(filtered)

        # 保存到数据库
        save_success = save_seat_layout_to_db(room_number, seat_layout, target_date)

        return jsonify({
            'success': True,
            'seat_layout': seat_layout,
            'saved': save_success
        })
    except Exception as e:
        print(f"生成座位布局错误: {str(e)}")
        print(traceback.format_exc())
        return jsonify({
            'success': False,
            'message': f"生成座位布局失败: {str(e)}"
        }), 500

@bp.route('/save_schedule/<room_number>', methods=['POST'])
@login_required
def save_schedule_endpoint(room_number):
    """保存值班表到数据库API"""
    try:
        schedule_data = request.json.get('schedule')
        target_date = request.json.get('target_date')
        if not schedule_data:
            return jsonify({'success': False, 'message': '缺少排班数据'}), 400

        success = save_schedule_to_db(room_number, schedule_data, target_date)

        return jsonify({
            'success': success,
            'message': '保存成功' if success else '保存失败'
        })
    except Exception as e:
        print(f"保存值班表错误: {str(e)}")
        print(traceback.format_exc())
        return jsonify({
            'success': False,
            'message': f"保存值班表失败: {str(e)}"
        }), 500

@bp.route('/save_bed_layout/<room_number>', methods=['POST'])
@login_required
def save_bed_layout_endpoint(room_number):
    """保存铺位布局到数据库API"""
    try:
        data = request.json
        bed_data = data.get('bed_data')
        target_date = data.get('target_date')

        if bed_data is None:
            return jsonify({'success': False, 'message': '缺少铺位数据'}), 400

        success = save_bed_layout_to_db(room_number, bed_data, target_date)

        return jsonify({
            'success': success,
            'message': '保存成功' if success else '保存失败'
        })
    except Exception as e:
        print(f"保存铺位布局错误: {str(e)}")
        print(traceback.format_exc())
        return jsonify({
            'success': False,
            'message': f"保存铺位布局失败: {str(e)}"
        }), 500

@bp.route('/save_seat_layout/<room_number>', methods=['POST'])
@login_required
def save_seat_layout_endpoint(room_number):
    """保存座位布局到数据库API"""
    try:
        data = request.json
        seat_data = data.get('seat_data')
        target_date = data.get('target_date')

        if seat_data is None:
            return jsonify({'success': False, 'message': '缺少座位数据'}), 400

        success = save_seat_layout_to_db(room_number, seat_data, target_date)

        return jsonify({
            'success': success,
            'message': '保存成功' if success else '保存失败'
        })
    except Exception as e:
        print(f"保存座位布局错误: {str(e)}")
        print(traceback.format_exc())
        return jsonify({
            'success': False,
            'message': f"保存座位布局失败: {str(e)}"
        }), 500

@bp.route('/bed_edit')
@login_required
def bed_edit():
    """铺位编辑页面"""
    room_number = request.args.get('room_number')
    user_id = request.args.get('user_id')
    target_date = request.args.get('date') or datetime.now().strftime('%Y-%m-%d')
    
    # 验证用户权限
    if str(session.get('user_id')) != user_id:
        return redirect(url_for('main.index'))
    
    """room = get_room_by_id(room_number)
    if not room:
        return redirect(url_for('main.index'))"""
    
    # 获取本周的值班表数据(包含铺位信息)
    schedule_data = get_schedule_by_date(room_number, target_date)
    beds = []
    
    if schedule_data and 'bed_data' in schedule_data:
        # 转换bed_data格式为前端需要的结构，包含FXDJ和BHLX字段
        bed_data = json.loads(schedule_data['bed_data'])
        for position, person in enumerate(bed_data, start=1):
            beds.append({
                'position': position,
                'person': person if person else None
            })
    
    print(f"Rendering bed_edit template with user_id: {user_id}")  # 调试信息
    return render_template('bed_edit.html', 
                         room_number=room_number,
                         user_id=user_id,
                         total=len(beds),
                         beds=beds,
                         target_date=target_date)


@bp.route('/edit_schedule/<room_number>')
@login_required
def edit_schedule(room_number):
    """值班表编辑页面"""
    try:
        # 权限验证
        user_type = session.get('user_type', 'normal')
        user_room_numbers = session.get('room_numbers', [])
        if user_type == 'normal' and room_number not in user_room_numbers:
            flash('您没有权限编辑该房间的值班表', 'error')
            return redirect(url_for('main.index'))

        # 计算当前周日期范围
        today = datetime.now().date()
        days_to_monday = today.weekday()
        current_monday = today - timedelta(days=days_to_monday)
        week_dates = [current_monday + timedelta(days=i) for i in range(7)]

        # 获取选择的日期
        selected_date_str = request.args.get('date', today.strftime('%Y-%m-%d'))
        try:
            selected_date = datetime.strptime(selected_date_str, '%Y-%m-%d').date()
        except:
            selected_date = today

        # 验证选择的日期是否在当前周
        if selected_date < current_monday or selected_date > current_monday + timedelta(days=6):
            selected_date = today

        # 获取人员数据
        with app_state.lock:
            persons = [
                {'id': p['id'], 'name': p.get('name', '')}
                for p in app_state.persons
                if isinstance(p, dict)
                   and str(p.get('room_number')) == room_number
                   and p.get('join_date')
            ]

        # 获取值班表数据
        schedule_result = get_schedule_by_date(room_number, current_monday.strftime('%Y-%m-%d'))
        if not schedule_result or not schedule_result.get('schedule_data'):
            flash('获取值班表数据失败', 'error')
            return redirect(url_for('main.room_detail', room_number=room_number))

        schedule = json.loads(schedule_result['schedule_data'])
        if not isinstance(schedule, list):
            schedule = [schedule]

        # 准备班次数据
        shifts = {}
        for day_data in schedule:
            try:
                day_date = datetime.strptime(day_data.get('date'), '%Y-%m-%d').date()
                if day_date == selected_date:
                    shifts = day_data.get('shifts', {
                        '午班': [],
                        '夜班1': [],
                        '夜班2': [],
                        '夜班3': []
                    })
                    break
            except:
                continue

        # 准备原始班次数据
        original_shifts = {}
        for day_data in schedule:
            if day_data['date'] == selected_date.strftime('%Y-%m-%d'):
                original_shifts = day_data['shifts']
                break

        return render_template(
            'schedule_edit.html',
            room_number=room_number,
            persons=persons,
            shifts=shifts,
            original_shifts=original_shifts,
            week_dates=week_dates,
            selected_date=selected_date.strftime('%Y-%m-%d'),
            today=today.strftime('%Y-%m-%d')
        )

    except Exception as e:
        print(f"编辑值班表错误: {str(e)}")
        traceback.print_exc()
        flash('处理值班表时发生系统错误', 'error')
        return redirect(url_for('main.room_detail', room_number=room_number))
    
@bp.route('/get_schedule_by_date/<room_number>')
@login_required
def get_schedule_by_date_api(room_number):
    """获取指定日期的班次数据API"""
    try:
        # 获取日期参数
        target_date_str = request.args.get('date')
        if not target_date_str:
            return jsonify({'success': False, 'message': '缺少日期参数'}), 400

        # 解析日期
        try:
            target_date = datetime.strptime(target_date_str, '%Y-%m-%d').date()
        except ValueError:
            return jsonify({'success': False, 'message': '日期格式错误'}), 400

        # 计算周一日期
        days_to_monday = target_date.weekday()
        monday_date = target_date - timedelta(days=days_to_monday)
        monday_str = monday_date.strftime('%Y-%m-%d')

        # 获取值班表数据
        schedule_result = get_schedule_by_date(room_number, monday_str)
        if not schedule_result or not schedule_result.get('schedule_data'):
            return jsonify({'success': False, 'message': '获取值班表数据失败'}), 400

        schedule = json.loads(schedule_result['schedule_data'])
        if not isinstance(schedule, list):
            schedule = [schedule]

        # 查找指定日期的班次数据
        shifts = {}
        for day_data in schedule:
            try:
                day_date = datetime.strptime(day_data.get('date'), '%Y-%m-%d').date()
                if day_date == target_date:
                    shifts = day_data.get('shifts', {
                        '午班': [],
                        '夜班1': [],
                        '夜班2': [],
                        '夜班3': []
                    })
                    break
            except:
                continue

        return jsonify({
            'success': True,
            'shifts': shifts
        })
    except Exception as e:
        print(f"获取班次数据错误: {str(e)}")
        traceback.print_exc()
        return jsonify({'success': False, 'message': f"获取班次数据失败: {str(e)}"}), 500


@bp.route('/save_schedule_edit/<room_number>', methods=['POST'])
@login_required
def save_schedule_edit(room_number):
    """保存值班表编辑API"""
    try:
        # 验证用户权限
        user_type = session.get('user_type', 'normal')
        user_room_numbers = session.get('room_numbers', [])
        
        if user_type == 'normal' and room_number not in user_room_numbers:
            return jsonify({
                'success': False,
                'message': '无权限操作'
            }), 403

        # 获取JSON格式请求数据
        data = request.json
        if not data:
            return jsonify({
                'success': False,
                'message': '请求数据格式错误'
            }), 400

        # 验证必要字段
        date = data.get('date')
        shifts = data.get('shifts')
        reason = data.get('change_reason')
        
        if not date or not shifts or not reason:
            return jsonify({
                'success': False,
                'message': '缺少必要参数'
            }), 400

        # 获取当前值班表
        target_date = datetime.strptime(date, '%Y-%m-%d').date()
        days_to_monday = target_date.weekday()
        monday = target_date - timedelta(days=days_to_monday)
        week = monday.strftime('%Y-%m-%d')

        schedule_result = get_schedule_by_date(room_number, date)
        if not schedule_result or not schedule_result.get('schedule_data'):
            return jsonify({
                'success': False,
                'message': '找不到指定的值班表'
            }), 404

        schedule = json.loads(schedule_result['schedule_data'])

        # 更新班次人员
        for day_data in schedule:
            if day_data['date'] == date:
                print(f"原始班次数据: {day_data['shifts']}")  # 调试日志
                print(f"新班次数据: {shifts}")  # 调试日志
                
                # 清空原有班次但保留结构
                for shift in day_data['shifts']:
                    day_data['shifts'][shift] = []
                
                # 更新新班次
                for shift_name, person_data in shifts.items():
                    if not person_data:
                        continue
                        
                    # 确保person_data是列表
                    if not isinstance(person_data, list):
                        person_data = [person_data]
                        
                    # 查找人员信息
                    person_list = []
                    with app_state.lock:
                        for person_id in person_data:
                            # 处理可能是对象或ID的情况
                            person_id = person_id.get('id', person_id) if isinstance(person_id, dict) else person_id
                            
                            for p in app_state.persons:
                                if str(p.get('id')) == str(person_id):
                                    person_list.append({
                                        'id': p['id'],
                                        'join_date': p.get('join_date').strftime('%Y-%m-%d'),
                                        'name': p.get('name', ''),
                                        'room_number': p.get('room_number')
                                    })
                                    break
                    
                    if person_list:
                        day_data['shifts'][shift_name] = person_list
                
                print(f"更新后班次数据: {day_data['shifts']}")  # 调试日志

        # 保存到数据库
        success = save_schedule_to_db(
            room_number=room_number,
            schedule_data=schedule,
            target_date=week
        )

        # 比较新旧班次数据并生成变更描述
        def compare_shifts(old_shifts, new_shifts):
            changes = []
            for shift_name in set(old_shifts.keys()).union(new_shifts.keys()):
                old_shift = old_shifts.get(shift_name, [])
                new_shift = new_shifts.get(shift_name, [])
                
                # 比较每个位置的人员
                for i in range(max(len(old_shift), len(new_shift))):
                    old_person = old_shift[i] if i < len(old_shift) else None
                    new_person = new_shift[i] if i < len(new_shift) else None
                    
                    # 只记录人员变更的情况，统一ID类型为字符串比较
                    if old_person and new_person and str(old_person['id']) != str(new_person['id']):
                        changes.append(f"{shift_name}：{old_person['name']}—>{new_person['name']}")
            
            return changes if changes else ["无人员变动"]

        old_shifts = request.json.get('original_shifts', {})
        new_shifts = shifts
        # 使用前端提交的新旧数据生成变更描述
        change_desc = compare_shifts(old_shifts, new_shifts)
        change_description = f"{date}班次变更:\\n" + "\\n".join(change_desc)

        # 保存变更记录
        if success:
            change_record_success = save_schedule_change_record(
                room_number=room_number,
                user_id=session.get('user_id'),
                change_description=change_description,
                change_reason=reason,
                schedule_data=schedule
            )
            if not change_record_success:
                print("警告: 值班表顺序保存成功，但变更记录保存失败")

        return jsonify({
            'success': success,
            'message': '值班表修改已保存' if success else '保存失败'
        })
    except Exception as e:
        print(f"保存值班表编辑错误: {str(e)}")
        print(traceback.format_exc())
        return jsonify({
            'success': False,
            'message': f"保存值班表编辑失败: {str(e)}"
        }), 500

@bp.route('/seat_edit')
@login_required
def seat_edit():
    """座位编辑页面"""
    room_number = request.args.get('room_number')
    user_id = request.args.get('user_id')
    target_date = request.args.get('date') or datetime.now().strftime('%Y-%m-%d')
    
    # 验证用户权限
    if str(session.get('user_id')) != user_id:
        return redirect(url_for('main.index'))
    
    # 获取本周的值班表数据(包含座位信息)
    schedule_data = get_schedule_by_date(room_number, target_date)
    seats = []
    
    if schedule_data and 'seat_data' in schedule_data:
        # 转换seat_data格式为前端需要的结构
        seat_data = json.loads(schedule_data['seat_data'])
        for position, person in enumerate(seat_data, start=1):
            seats.append({
                'position': position,
                'person': person if person else None
            })
    
    print(f"Rendering seat_edit template with user_id: {user_id}")  # 调试信息
    return render_template('seat_edit.html', 
                         room_number=room_number,
                         user_id=user_id,
                         total=len(seats),
                         seats=seats,
                         target_date=target_date)

@bp.route('/save_bed_order', methods=['POST'])
@login_required
def save_bed_order():
    """保存铺位顺序API"""
    try:
        data = request.get_json()
        room_id = data['room_number']
        beds = data['beds']
        target_date = data.get('date') or datetime.now().strftime('%Y-%m-%d')
        
        # 验证用户权限
        user_id = data.get('user_id')
        if not user_id:
            return jsonify({'success': False, 'message': '缺少用户ID参数'}), 400
            
        if str(session.get('user_id')) != user_id:
            return jsonify({'success': False, 'message': '无权限操作'}), 403
        
        # 获取现有bed_data以保留FXDJ和BHLX字段
        existing_schedule = get_schedule_by_date(room_id, target_date)
        existing_bed_data = []
        if existing_schedule and 'bed_data' in existing_schedule:
            try:
                existing_bed_data = json.loads(existing_schedule['bed_data'])
            except (json.JSONDecodeError, TypeError):
                existing_bed_data = []
        
        # 创建一个映射，以便快速查找现有数据中的FXDJ和BHLX字段
        existing_person_map = {}
        for bed in existing_bed_data:
            if bed and 'id' in bed:
                existing_person_map[bed['id']] = bed
        
        # 数据清洗和转换
        bed_data = []
        for bed in beds:
            if not bed:  # 处理空铺位
                bed_data.append(None)
                continue
                
            try:
                # 验证必要字段
                if not all(k in bed for k in ['person_id', 'person_name', 'new_position']):
                    raise ValueError('缺少必要字段')
                
                # 获取现有数据中的FXDJ和BHLX字段，如果不存在则使用默认值
                existing_person = existing_person_map.get(bed['person_id'], {})
                fxdj = existing_person.get('FXDJ', 0)
                bhlx = existing_person.get('BHLX', 0)
                
                # 转换为数据库格式，包含FXDJ和BHLX字段
                bed_data.append({
                    'id': bed['person_id'],
                    'name': bed['person_name'],
                    'position': bed['new_position'],
                    'join_date': bed.get('join_date'),
                    'FXDJ': fxdj,
                    'BHLX': bhlx
                })
            except Exception as e:
                print(f"数据格式错误: {str(e)}")
                continue
        
        # 按位置排序
        sorted_beds = sorted(
            [b for b in bed_data if b is not None],
            key=lambda x: x['position']
        )
        
        # 保存铺位顺序到主表
        success = save_bed_layout_to_db(
            room_number=room_id,
            bed_data=sorted_beds,
            target_date=target_date
        )
        
        # 同时保存变更记录到历史表
        if success:
            change_record_success = save_bed_change_record(
                room_number=room_id,
                user_id=user_id,
                operation_time=datetime.now().isoformat(),
                change_description=data.get('change_description', ''),
                change_reason=data.get('change_reason', ''),
                beds_data=sorted_beds
            )
            if not change_record_success:
                print("警告: 铺位顺序保存成功，但变更记录保存失败")
        
        return jsonify({
            'success': success,
            'message': '铺位顺序保存成功' if success else '保存失败'
        })
    except Exception as e:
        print(f"保存铺位顺序错误: {str(e)}")
        print(traceback.format_exc())
        return jsonify({
            'success': False,
            'message': f"保存铺位顺序失败: {str(e)}"
        }), 500

@bp.route('/record')
@login_required
def record():
    """调整记录审计页面"""
    try:
        # 获取查询参数
        record_type = request.args.get('type', '')
        start_date = request.args.get('start_date', '')
        end_date = request.args.get('end_date', '')
        sort_field = request.args.get('sort', 'time')
        page = int(request.args.get('page', 1))
        per_page = 20

        # 构建查询条件
        query = {}
        if record_type:
            query['type'] = record_type
        if start_date:
            query['create_time__gte'] = datetime.strptime(start_date, '%Y-%m-%d')
        if end_date:
            query['create_time__lte'] = datetime.strptime(end_date, '%Y-%m-%d') + timedelta(days=1)

        # 权限过滤 - 普通用户只能查看自己房间的记录
        user_type = session.get('user_type', 'normal')
        if user_type == 'normal':
            user_room_numbers = session.get('room_numbers', [])
            query['room_number__in'] = user_room_numbers

        # 获取记录总数
        total_records = get_record_count(query)

        # 获取分页记录
        records = get_records(
            query=query,
            sort=sort_field,
            skip=(page-1)*per_page,
            limit=per_page
        )

        # 转换记录类型显示名称
        type_display_map = {
            'bed': '铺位调整',
            'seat': '座位调整',
            'schedule': '值班表调整'
        }
        for r in records:
            r['type_display'] = type_display_map.get(r['type'], r['type'])

        return render_template(
            'record.html',
            records=records,
            current_page=page,
            total_pages=(total_records + per_page - 1) // per_page,
            record_type=record_type,
            start_date=start_date,
            end_date=end_date,
            sort_field=sort_field
        )

    except Exception as e:
        print(f"获取调整记录错误: {str(e)}")
        traceback.print_exc()
        flash('获取调整记录时发生错误', 'error')
        return redirect(url_for('main.index'))

@bp.route('/save_seat_order', methods=['POST'])
@login_required
def save_seat_order():
    """保存座位顺序API"""
    try:
        data = request.get_json()
        room_id = data['room_number']
        seats = data['seats']
        target_date = data.get('date') or datetime.now().strftime('%Y-%m-%d')
        
        # 验证用户权限
        user_id = data.get('user_id')
        if not user_id:
            return jsonify({'success': False, 'message': '缺少用户ID参数'}), 400
            
        if str(session.get('user_id')) != user_id:
            return jsonify({'success': False, 'message': '无权限操作'}), 403
        
        # 获取现有seat_data以保留原有字段
        existing_schedule = get_schedule_by_date(room_id, target_date)
        existing_seat_data = []
        if existing_schedule and 'seat_data' in existing_schedule:
            try:
                existing_seat_data = json.loads(existing_schedule['seat_data'])
            except (json.JSONDecodeError, TypeError):
                existing_seat_data = []
        
        # 创建一个映射，以便快速查找现有数据中的字段
        existing_person_map = {}
        for seat in existing_seat_data:
            if seat and 'id' in seat:
                existing_person_map[seat['id']] = seat
        
        # 数据清洗和转换
        seat_data = []
        for seat in seats:
            if not seat:  # 处理空座位
                seat_data.append(None)
                continue
                
            try:
                # 验证必要字段
                if not all(k in seat for k in ['person_id', 'person_name', 'new_position']):
                    raise ValueError('缺少必要字段')
                
                # 获取现有数据中的字段
                existing_person = existing_person_map.get(seat['person_id'], {})
                
                # 转换为数据库格式
                seat_data.append({
                    'id': seat['person_id'],
                    'name': seat['person_name'],
                    'position': seat['new_position'],
                    'join_date': seat.get('join_date'),
                    # 保留现有数据中的其他字段
                    **{k: v for k, v in existing_person.items() if k not in ['id', 'name', 'position', 'join_date']}
                })
            except Exception as e:
                print(f"数据格式错误: {str(e)}")
                continue
        
        # 按位置排序
        sorted_seats = sorted(
            [s for s in seat_data if s is not None],
            key=lambda x: x['position']
        )
        
        # 保存座位顺序到主表
        success = save_seat_layout_to_db(
            room_number=room_id,
            seat_data=sorted_seats,
            target_date=target_date
        )
        
        # 同时保存变更记录到历史表
        if success:
            change_record_success = save_seat_change_record(
                room_number=room_id,
                user_id=user_id,
                operation_time=datetime.now().isoformat(),
                change_description=data.get('change_description', ''),
                change_reason=data.get('change_reason', ''),
                seats_data=sorted_seats
            )
            if not change_record_success:
                print("警告: 座位顺序保存成功，但变更记录保存失败")
        
        return jsonify({
            'success': success,
            'message': '座位顺序保存成功' if success else '保存失败'
        })
    except Exception as e:
        print(f"保存座位顺序错误: {str(e)}")
        print(traceback.format_exc())
        return jsonify({
            'success': False,
            'message': f"保存座位顺序失败: {str(e)}"
        }), 500
        
@bp.route('/api/room/<room_number>/seats', methods=['GET'])
@login_required
def api_get_room_seats(room_number):
    """API - 获取房间座位数据"""
    try:
        # 获取当前用户信息
        user_type = session.get('user_type', 'normal')
        user_room_numbers = session.get('room_numbers', [])
        
        # 检查普通用户是否有权限访问该房间
        if user_type == 'normal' and room_number not in user_room_numbers:
            return jsonify({'error': '您没有权限访问该房间'}), 403
        
        # 获取选择的日期或周偏移
        week_offset = request.args.get('week_offset', '0')
        try:
            week_offset = int(week_offset)
        except ValueError:
            week_offset = 0
            
        selected_week = request.args.get('week', None)
        if selected_week:
            target_date = selected_week
        else:
            # 根据周偏移计算目标日期
            today = datetime.now().date()
            target_date = (today + timedelta(days=week_offset * 7)).strftime('%Y-%m-%d')
        
        # 获取当周座位数据
        schedule_result = get_schedule_by_date(room_number, target_date)
        
        if not schedule_result or 'seat_data' not in schedule_result or not schedule_result['seat_data']:
            return jsonify({'seat1': [], 'seat2': []}), 200
        
        # 处理座位数据
        seat_data = {'seat1': [], 'seat2': []}
        raw_seat_data = json.loads(schedule_result['seat_data'])
        
        # 假设前27个是seat1区域，后9个是seat2区域
        # 这里的分配逻辑可能需要根据实际情况调整
        for i, person in enumerate(raw_seat_data):
            seat_info = {
                'number': i + 1,
                'person': person
            }
            if i < 27:  # 前27个座位属于seat1区域
                seat_data['seat1'].append(seat_info)
            else:  # 后面的座位属于seat2区域
                seat_data['seat2'].append(seat_info)
        
        return jsonify(seat_data)
    except Exception as e:
        print(f"获取座位数据错误: {str(e)}")
        print(traceback.format_exc())
        return jsonify({'error': f"获取座位数据失败: {str(e)}"}), 500

@bp.route('/api/room/<room_number>/beds', methods=['GET'])
@login_required
def api_get_room_beds(room_number):
    """API - 获取房间铺位数据"""
    try:
        # 获取当前用户信息
        user_type = session.get('user_type', 'normal')
        user_room_numbers = session.get('room_numbers', [])
        
        # 检查普通用户是否有权限访问该房间
        if user_type == 'normal' and room_number not in user_room_numbers:
            return jsonify({'error': '您没有权限访问该房间'}), 403
        
        # 获取选择的日期或周偏移
        week_offset = request.args.get('week_offset', '0')
        try:
            week_offset = int(week_offset)
        except ValueError:
            week_offset = 0
            
        selected_week = request.args.get('week', None)
        if selected_week:
            target_date = selected_week
        else:
            # 根据周偏移计算目标日期
            today = datetime.now().date()
            target_date = (today + timedelta(days=week_offset * 7)).strftime('%Y-%m-%d')
        
        # 获取当周铺位数据
        schedule_result = get_schedule_by_date(room_number, target_date)
        
        if not schedule_result or 'bed_data' not in schedule_result or not schedule_result['bed_data']:
            return jsonify({'bed1': [], 'bed2': [], 'bed3': []}), 200
        
        # 处理铺位数据
        bed_data = {'bed1': [], 'bed2': [], 'bed3': []}
        raw_bed_data = json.loads(schedule_result['bed_data'])
        
        # 假设前13个是bed1区域，接下来3个是bed2区域，剩下的是bed3区域
        # 这里的分配逻辑可能需要根据实际情况调整
        for i, person in enumerate(raw_bed_data):
            bed_info = {
                'number': i + 1,
                'person': person
            }
            if i < 13:  # 前13个铺位属于bed1区域
                bed_data['bed1'].append(bed_info)
            elif i < 16:  # 接下来3个铺位属于bed2区域
                bed_data['bed2'].append(bed_info)
            else:  # 剩下的铺位属于bed3区域
                bed_data['bed3'].append(bed_info)
        
        return jsonify(bed_data)
    except Exception as e:
        print(f"获取铺位数据错误: {str(e)}")
        print(traceback.format_exc())
        return jsonify({'error': f"获取铺位数据失败: {str(e)}"}), 500

@bp.route('/print/<room_number>', methods=['GET', 'POST'])
@login_required
def print_schedule(room_number):
    """打印排班表页面 - 完全从room页面获取数据"""
    try:
        # 权限验证
        user_type = session.get('user_type', 'normal')
        user_room_numbers = session.get('room_numbers', [])
        if user_type == 'normal' and room_number not in user_room_numbers:
            flash('您没有权限访问该房间', 'error')
            return redirect(url_for('main.index'))

        # 获取基础参数
        if request.method == 'POST':
            selected_week = request.form.get('week', datetime.now().strftime('%Y-%m-%d'))
            week_offset = int(request.form.get('week_offset', 0))
        else:
            selected_week = request.args.get('week', datetime.now().strftime('%Y-%m-%d'))
            week_offset = int(request.args.get('week_offset', 0))
        selected_date = datetime.strptime(selected_week, '%Y-%m-%d').date()
        
        # 计算周日期范围
        days_to_monday = selected_date.weekday()
        week_monday = selected_date - timedelta(days=days_to_monday)
        week_sunday = week_monday + timedelta(days=6)
        
        # 安全获取并解析布局数据
        def safe_get_data(param_name, default):
            if request.method == 'POST':
                data = request.form.get(param_name, default)
            else:
                data = request.args.get(param_name, default)
            try:
                return json.loads(data)
            except json.JSONDecodeError:
                return json.loads(default)

        # 从请求获取完整布局数据
        layout_data = {
            'seat': {
                'rows': int(request.form.get('seat_rows', request.args.get('seat_rows', 6))),
                'data': safe_get_data('seat_data', '[]')
            },
            'bed1': {
                'rows': int(request.form.get('bed1_rows', request.args.get('bed1_rows', 3))),
                'data': safe_get_data('bed1_data', '[]')
            },
            'bed2': {
                'rows': int(request.form.get('bed2_rows', request.args.get('bed2_rows', 3))), 
                'data': safe_get_data('bed2_data', '[]')
            },
            'bed3': {
                'rows': int(request.form.get('bed3_rows', request.args.get('bed3_rows', 3))),
                'cols': int(request.form.get('bed3_cols', request.args.get('bed3_cols', 3))),
                'data': safe_get_data('bed3_data', '[]')
            }
        }

        # 获取排班表数据
        schedule_result = get_schedule_by_date(room_number, selected_week)
        schedule = []
        
        if schedule_result and schedule_result.get('schedule_data'):
            try:
                schedule = json.loads(schedule_result['schedule_data'])
            except json.JSONDecodeError:
                schedule = []
        else:
            # 生成空排班表
            for i in range(7):
                current_date = week_monday + timedelta(days=i)
                schedule.append({
                    'date': current_date.strftime('%Y-%m-%d'),
                    'shifts': {
                        '午班': [],
                        '夜班1': [],
                        '夜班2': [],
                        '夜班3': []
                    }
                })

        # 生成周日期标签（只显示周几）
        weekdays = ['周一','周二','周三','周四','周五','周六','周日']

        # 获取座位和铺位数据
        seat_data = []
        bed_data = []
        
        if schedule_result:
            if 'seat_data' in schedule_result and schedule_result['seat_data']:
                try:
                    seat_data = json.loads(schedule_result['seat_data'])
                    # 确保数据格式正确
                    seat_data = [
                        {
                            'name': item.get('name', ''),
                            'join_date': datetime.strptime(item['join_date'], '%Y-%m-%d') 
                                if item.get('join_date') and isinstance(item['join_date'], str)
                                else None
                        }
                        for item in seat_data if item
                    ]
                except Exception as e:
                    print(f"解析座位数据错误: {str(e)}")
                    seat_data = []
            
            if 'bed_data' in schedule_result and schedule_result['bed_data']:
                try:
                    bed_data = json.loads(schedule_result['bed_data'])
                    # 确保数据格式正确
                    bed_data = [
                        {
                            'name': item.get('name', ''),
                            'join_date': datetime.strptime(item['join_date'], '%Y-%m-%d') 
                                if item.get('join_date') and isinstance(item['join_date'], str)
                                else None
                        }
                        for item in bed_data if item
                    ]
                except Exception as e:
                    print(f"解析铺位数据错误: {str(e)}")
                    bed_data = []

        # 计算行数
        seat_rows = len(seat_data) if seat_data else 0
        bed_rows = len(bed_data) if bed_data else 0

        return render_template(
            'print.html',
            room_number=room_number,
            schedule=schedule,
            week_info={
                'selected_week': selected_week,
                'offset': week_offset,
                'monday': week_monday,
                'sunday': week_sunday,
                'day_labels': weekdays
            },
            time_slots=['午班', '夜班1', '夜班2', '夜班3'],
            seat_data=seat_data,
            bed_data=bed_data,
            seat_rows=seat_rows,
            bed_rows=bed_rows
        )
           
    except Exception as e:
        print(f"打印排班表错误: {str(e)}")
        print(traceback.format_exc())
        flash('处理打印排班表时发生系统错误', 'error')
        return redirect(url_for('main.room_detail', room_number=room_number))

@bp.route('/admin/users', methods=['GET', 'POST'])
@login_required
def user_management():
    """用户管理页面 - 仅管理员可见"""
    # 检查用户权限
    if session.get('user_type') != 'admin':
        if request.method == 'POST':
            return jsonify({'error': '您没有权限执行此操作'}), 403
        flash('您没有权限访问此页面', 'error')
        return redirect(url_for('main.index'))
    
    # 处理添加用户请求
    if request.method == 'POST':
        try:
            # 获取JSON数据
            data = request.get_json()
            username = data.get('username')
            password = data.get('password')
            user_type = data.get('user_type', 'normal')
            full_name = data.get('full_name')
            phone = data.get('phone')
            role_id = data.get('role_id')
            
            # 验证输入数据
            if not username or not password:
                return jsonify({'error': '用户名和密码不能为空'}), 400
            
            # 检查用户名是否已存在
            if check_username_exists(username):
                return jsonify({'error': '用户名已存在'}), 400
            
            # 创建用户（普通用户默认没有房间权限）
            room_numbers = []
            if create_user(username, password, room_numbers, user_type, full_name, phone, role_id):
                return jsonify({'success': True})
            else:
                return jsonify({'error': '创建用户失败'}), 500
                
        except Exception as e:
            print(f"创建用户错误: {str(e)}")
            return jsonify({'error': '服务器内部错误'}), 500
    
    # 获取所有用户
    users = get_all_users()
    # 获取所有房间号
    rooms = get_all_room_numbers()
    # 获取所有角色
    roles = get_all_roles()
    
    # 获取当前用户信息
    current_user = {
        'is_authenticated': 'user_id' in session,
        'username': session.get('username', ''),
        'user_type': session.get('user_type', 'normal'),
        'id': session.get('user_id')
    }
    
    return render_template('user_management.html', users=users, rooms=rooms, roles=roles, current_user=current_user)

@bp.route('/admin/users/<int:user_id>/permissions', methods=['POST'])
@login_required
def update_user_permissions(user_id):
    """更新用户房间权限 - 仅管理员可见"""
    # 检查用户权限
    if session.get('user_type') != 'admin':
        return jsonify({'error': '您没有权限执行此操作'}), 403
    
    # 获取房间权限数据
    room_numbers = request.json.get('room_numbers', [])
    
    # 更新用户权限
    if update_user_room_permissions(user_id, room_numbers):
        return jsonify({'success': True})
    else:
        return jsonify({'error': '更新用户权限失败'}), 500

@bp.route('/admin/users/<int:user_id>', methods=['DELETE'])
@login_required
def delete_user_route(user_id):
    """删除用户 - 仅管理员可见"""
    # 检查用户权限
    if session.get('user_type') != 'admin':
        return jsonify({'error': '您没有权限执行此操作'}), 403
    
    # 不能删除自己
    if user_id == session.get('user_id'):
        return jsonify({'error': '不能删除自己的账户'}), 400
    
    # 删除用户
    if delete_user(user_id):
        return jsonify({'success': True})
    else:
        return jsonify({'error': '删除用户失败'}), 500

@bp.route('/admin/users/<int:user_id>/info', methods=['POST'])
@login_required
def update_user_info(user_id):
    """更新用户信息 - 仅管理员可见"""
    # 检查用户权限
    if session.get('user_type') != 'admin':
        return jsonify({'error': '您没有权限执行此操作'}), 403
    
    # 获取用户信息数据
    data = request.get_json()
    full_name = data.get('full_name')
    phone = data.get('phone')
    role_id = data.get('role_id')
    
    # 更新用户信息
    if update_user_information(user_id, full_name, phone, role_id):
        return jsonify({'success': True})
    else:
        return jsonify({'error': '更新用户信息失败'}), 500

@bp.route('/api/users')
@login_required
def api_get_users():
    """API获取所有用户信息 - 仅管理员可见"""
    # 检查用户权限
    if session.get('user_type') != 'admin':
        return jsonify({'error': '您没有权限执行此操作'}), 403
    
    # 获取所有用户
    users = get_all_users()
    return jsonify(users)

@bp.route('/api/rooms')
@login_required
def api_get_rooms():
    """API获取所有房间号 - 仅管理员可见"""
    # 检查用户权限
    if session.get('user_type') != 'admin':
        return jsonify({'error': '您没有权限执行此操作'}), 403
    
    # 获取所有房间号
    rooms = get_all_room_numbers()
    return jsonify(rooms)


@bp.route('/relief_forms')
@login_required
def relief_forms():
    """接济单管理页面"""
    # 获取当前用户信息
    current_user = {
        'is_authenticated': 'user_id' in session,
        'username': session.get('username', ''),
        'user_type': session.get('user_type', 'normal'),
        'id': session.get('user_id'),
        'role_id': session.get('role_id', 0)  # 添加角色ID信息
    }
    
    # 获取接济单列表
    relief_forms = relief.get_relief_forms_by_role(current_user['id'], current_user['role_id'])
    
    return render_template('relief_forms.html', current_user=current_user, relief_forms=relief_forms)

@bp.route('/relief_forms/<int:form_id>')
@login_required
def relief_form_detail(form_id):
    """接济单详情页面"""
    # 获取当前用户信息
    current_user = {
        'is_authenticated': 'user_id' in session,
        'username': session.get('username', ''),
        'user_type': session.get('user_type', 'normal'),
        'id': session.get('user_id'),
        'role_id': session.get('role_id', 0)  # 添加角色ID信息
    }

    # 获取接济单详情
    relief_form = relief.get_relief_form(form_id)

    return render_template('relief_form_detail.html', form_id=form_id, current_user=current_user, relief_form=relief_form)

# 接济单API路由

@bp.route('/api/relief_forms', methods=['POST'])
@login_required
def create_relief_form():
    """创建接济单"""
    try:
        # 获取JSON数据
        data = request.get_json()
        
        # 从session获取开具人信息
        issuer_id = session.get('user_id')
        issuer_name = session.get('username')
        
        # 从前端获取接收人姓名和房间号
        recipient_name = data.get('recipient')
        room_number = data.get('room')
        
        # 查询接收人ID
        recipient_id = None
        if room_number and recipient_name:
            # 导入数据库函数
            from db import fetch_mysql_data
            
            # 获取所有人员数据
            persons_data = fetch_mysql_data()
            
            # 查找匹配的人员
            for person in persons_data:
                if person['room_number'] == room_number and person['name'] == recipient_name:
                    recipient_id = person['id']
                    break
        
        # 调用业务逻辑层创建接济单
        form_id = relief.create_relief_form(
            recipient_id=recipient_id,
            recipient_name=recipient_name,
            issuer_id=issuer_id,
            issuer_name=issuer_name,
            items=data.get('items', ''),
            remark=data.get('notes', ''),
            total_value=data.get('total_value', 0.0)
        )
        
        if form_id:
            return jsonify({'success': True, 'form_id': form_id})
        else:
            return jsonify({'error': '创建接济单失败'}), 500
            
    except Exception as e:
        print(f"创建接济单错误: {str(e)}")
        return jsonify({'error': '服务器内部错误'}), 500

@bp.route('/api/relief_forms', methods=['GET'])
@login_required
def get_relief_forms():
    """获取接济单列表"""
    try:
        # 调用业务逻辑层获取所有接济单
        forms = relief.get_all_relief_forms()
        return jsonify(forms)
        
    except Exception as e:
        print(f"获取接济单列表错误: {str(e)}")
        return jsonify({'error': '服务器内部错误'}), 500

@bp.route('/api/relief_forms/<int:form_id>', methods=['GET'])
@login_required
def get_relief_form(form_id):
    """获取接济单详情"""
    try:
        # 调用业务逻辑层获取接济单详情
        form = relief.get_relief_form(form_id)
        if form:
            return jsonify(form)
        else:
            return jsonify({'error': '未找到接济单'}), 404
            
    except Exception as e:
        print(f"获取接济单详情错误: {str(e)}")
        return jsonify({'error': '服务器内部错误'}), 500

@bp.route('/api/relief_forms/<int:form_id>/status', methods=['PUT'])
@login_required
def update_relief_form_status(form_id):
    """更新接济单状态"""
    try:
        # 获取JSON数据
        data = request.get_json()
        status = data.get('status')
        
        # 从session获取操作用户信息
        user_id = session.get('user_id')
        user_name = session.get('username')
        
        # 调用业务逻辑层更新接济单状态
        success = relief.update_relief_form_status(form_id, status, user_id, user_name)
        
        if success:
            return jsonify({'success': True})
        else:
            return jsonify({'error': '更新接济单状态失败'}), 500
            
    except Exception as e:
        print(f"更新接济单状态错误: {str(e)}")
        return jsonify({'error': '服务器内部错误'}), 500


@bp.route('/api/relief_forms/role', methods=['GET'])
@login_required
def get_relief_forms_by_role():
    """根据用户角色获取接济单列表"""
    try:
        # 从session获取用户信息
        user_id = session.get('user_id')
        user_role = session.get('role_id')
        
        # 调用业务逻辑层获取接济单列表
        forms = relief.get_relief_forms_by_role(user_id, user_role)
        
        return jsonify(forms)
        
    except Exception as e:
        print(f"根据角色获取接济单列表错误: {str(e)}")
        return jsonify({'error': '服务器内部错误'}), 500

# 在文件末尾添加获取所有角色的函数
def get_all_roles():
    """获取所有角色"""
    conn = None
    cursor = None
    try:
        conn = mysql.connector.connect(**MYSQL_CONFIG)
        cursor = conn.cursor(dictionary=True)
        
        query = "SELECT id, name FROM roles ORDER BY id"
        cursor.execute(query)
        return cursor.fetchall()
    except mysql.connector.Error as db_err:
        print(f"获取角色列表错误: {str(db_err)}")
        return []
    except Exception as e:
        print(f"获取角色列表异常: {str(e)}")
        return []
    finally:
        if cursor: cursor.close()
        if conn and conn.is_connected(): conn.close()


@bp.route('/api/user/rooms', methods=['GET'])
@login_required
def api_get_user_rooms():
    """API获取用户有权限的所有房间号 - 供普通用户使用"""
    try:
        # 获取用户的房间权限
        user_rooms = session.get('room_numbers', [])
        return jsonify(user_rooms)
    except Exception as e:
        print(f"获取用户房间列表错误: {str(e)}")
        return jsonify({'error': '服务器内部错误'}), 500


@bp.route('/api/room/<room_number>/persons', methods=['GET'])
@login_required
def api_get_persons_by_room(room_number):
    """API根据房间号获取该房间所有人员列表"""
    try:
        # 导入数据库函数
        from db import fetch_mysql_data
        
        # 获取所有人员数据
        persons_data = fetch_mysql_data()
        
        # 筛选指定房间的人员
        room_persons = [person for person in persons_data if person['room_number'] == room_number]
        
        return jsonify(room_persons)
    except Exception as e:
        print(f"获取房间人员列表错误: {str(e)}")
        return jsonify({'error': '服务器内部错误'}), 500